
"use strict";

import {AngleCom, MeasureResult} from './AngleCom';
import * as q from 'q';
import * as co from 'co';
import {BaseController} from './../BaseController';

/** 
 * 控制倾角计的基础类,不同的测量控制器应继承自该类
 */
class AngleController extends BaseController {
    /** 
     * 控制倾角计的anglecom
     */
    public angleCom: AngleCom = null;
    
    /** 
     * 初始化控制器,打开com口
     */
    constructor(portName: string) {
        super();
        this.angleCom = new AngleCom(portName);
    }


    /** 
     * 倾角计测量点的集合
     */
    public deviceList: Array<AnglePoint> = [];   
   
    /** 
     * 测量前的一些准备工作,留在子类中实现
     */
    public preSurvey: () => void;   
 
    
    /** 
     * 倾角计测量,返回一组promise的测点数据
     * 构建一个AnglePoint的集合数据,测量完成后,将测量结果填入每个AnglePoint中,最终返回该AnglePoint的集合
     */
    public survey(): Promise<any> {
        //测量前的准备工作
        this.preSurvey && this.preSurvey();
        var resultPoints: Array<AnglePoint> = []; //准备好本次的测量点
        var _this = this;

        return co(function* () {
            if (_this._working) return null;
            yield q.delay(500);  //略微延迟一下,防止串口未打开
            try {
                for (let point of _this.deviceList) {
                    //测量该点
                    var result = yield _this.angleCom.survey(point.id);
                    yield q.delay(1000);
                    var pt = Object.assign(new AnglePoint(0, 0), point);
                    //如果能观测到数据
                    if (result && (result.x !== null || result.y !== null)) {
                        //赋值到该点的角度和距离
                        _this.parseResult(pt, result);
                    } else {
                        yield q.delay(100);
                    }
                    resultPoints.push(pt);
                }
                _this._working = false;
                return resultPoints;
            } catch (error) {
                _this._working = false;
                console.log('Error' + error);
                return resultPoints;
            }
        });
    }

    /** 
     * 根据倾角计返回原始数据，得到该点测量结果
     */
    public parseResult(point: AnglePoint, result: MeasureResult) {
        switch (point.angleType) {
            case 1:
                point.x = result.x * point.resolution;
                point.t = result.t;
                point.time = new Date();
                break;
            case 2:
                point.y = result.y * point.resolution;
                point.t = result.t;
                point.time = new Date();
                break;
            default:
                point.x = result.x * point.resolution;
                point.y = result.y * point.resolution;
                point.t = result.t;
                point.time = new Date();
                break;
        }
    }

}

/** 
 * 倾角计测量点
 */
class AnglePoint {
    /** 
    * 构造函数
    * @param {number} id 测量点编号 re 分辨率 
    */
    constructor(id?: number, re?: number) {
        this.id = id || 1;
        re && (this.resolution = re);
    }
    public id: number = 1;
    public x: number = null;
    public y: number = null;
    public t: number = null;
    public angleType: ResultType = 0;
    public resolution: number = 0.001;
    public time: Date = null; // 测量时间
    
}

/** 
 * 不同倾角计返回的有效数据类型不同
 * 单轴倾角计返回结果中只有X轴或Y轴数据是有效的；双轴倾角计返回的X、Y数据都有效
 */
enum ResultType {
    XYAngle = 0, // 倾角计X、Y双轴数据
    XAngle = 1,  // 倾角计X轴数据
    YAngle = 2 // 倾角计Y轴数据    
}

export {AngleController, AnglePoint, ResultType};